package com.putable.nmc.dmv.simulation;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.InputMismatchException;

import com.putable.nmc.dmv.Customer;
import com.putable.nmc.dmv.CustomerLine;
import com.putable.nmc.dmv.DMVDriver;
import com.putable.nmc.dmv.Door;
import com.putable.nmc.dmv.PQElement;
import com.putable.nmc.world.CIT;
import com.putable.nmc.world.World;
import com.putable.pqueue.PQueue;
import com.putable.pqueue.PQueueImpl;

public class Simulation {
	private World world;
	/**
     * Build a Simulation object.  If the length of the args array is 0, a
     * 'default' world is built, otherwise, the first argument is
     * treated as a filename and an attempt is made to load that
     * file as a world configuration.
     * 
     * @param args 
	 */
    public Simulation(String[] args) {
        if (args.length == 0) world = new World();  // Make a default world
        else {
            try {
                if (args.length != 2) 
                    throw new InputMismatchException("Need exactly two files");

                FileReader readStaff = new FileReader(args[0]);
                FileReader readWorld = new FileReader(args[1]);
                world = new World(readStaff, readWorld);
            } 
            catch (FileNotFoundException e) {
                System.err.println("Can't read "+args[0]);
                e.printStackTrace();
                System.exit(1);
            }
            catch (InputMismatchException e) {
                System.err.println("Problem loading "+args[0]);
                e.printStackTrace();
                System.exit(2);
            }
        }
	}
    /**
     * A method demonstrating acquiring and returning CIT objects from a World.
     * 
     * @return true if we 'won' the simulation
     * 
     */
    public boolean run() {

        double clock = 0.0;       // 0.0 is 8:00:00AM sharp!
        PQueue pq = new PQueueImpl();
        CustomerLine cLine = new CustomerLine();
        
        DMVDriver dmv = new DMVDriver();
        dmv.initialize(world, pq,  cLine);
        Door door = new Door(pq);
        while (true) {
            CIT cit = world.getNextCIT(clock);
            if (cit == null) break;     // break if end of day



            Customer cust = new Customer(pq, cit, world);
            door.addCustToPQ(clock, cust);
            //Jump the clock to the next event and run it
            PQElement nextPQE = (PQElement) pq.remove();
            clock = nextPQE.getTimeOfNextTask();
            nextPQE.run(clock, cLine);
            
        }
        
        // OK, no more customers.  Let's see how we did.
        Writer out = new StringWriter();
        boolean weWon = world.getScore(out);
        System.out.println(out.toString());
        return weWon;
	}
    
    public World getWorld(){
    	return world;
    }

    /**
     * A mainline to drive the demo
     * 
     * @param args
     *            Either an empty array, to build a default world, or an array
     *            whose first element is the name of a file to load a world
     *            configuration from.
     */
    public static void main(String[] args) {
		Simulation s = new Simulation(args);
		System.exit(s.run()?0:3);
        
	}
}
